package com.web.portal.service;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.web.portal.dao.BaseDao;



@Transactional
public abstract class DefaultWebPortalService<T> implements WebportalService<T> {
	private static final Logger LOG = Logger
			.getLogger(DefaultWebPortalService.class);

	private Class<T> type;
	protected BaseDao<T, Serializable> baseDao;

	public Class<T> getType() {
		return type;
	}

	public void setType(Class<T> type) {
		this.type = type;
	}

	public void setBaseDao(BaseDao<T, Serializable> baseDao) {
		this.baseDao = baseDao;
	}

	public DefaultWebPortalService() {
		super();
		// TODO Auto-generated constructor stub
		// Use reflection to determine which entity class this service deals
		// with
		// Note: we have to handle the weird case of this being a cglib proxy
		Type thisType = getClass().getGenericSuperclass();
		while (thisType instanceof Class) {
			// the while loops up the heirarchy in the case that a class extends
			// a genericised class.
			thisType = ((Class) thisType).getGenericSuperclass();
		} // end while

		final Type localType;
		if (thisType instanceof ParameterizedType) {
			localType = ((ParameterizedType) thisType).getActualTypeArguments()[0];
		} else {
			throw new IllegalArgumentException(
					"Problem handling type construction for " + getClass());
		}

		// handled nested generics (i.e. the grantsolutionsentity is
		// genericised)
		if (localType instanceof Class) {
			this.type = (Class<T>) localType;
		} else if (localType instanceof ParameterizedType) {
			this.type = (Class<T>) ((ParameterizedType) localType).getRawType();
		} else {
			throw new IllegalArgumentException(
					"Problem determining the class of the generic for "
							+ getClass());
		}
	}

	@Transactional
	
	public void createOrUpdate(T entity) throws RuntimeException {
		// TODO Auto-generated method stub

		try {
			baseDao.saveOrUpdate(entity);
		} catch (final Exception e) {
			LOG.debug("exception : rollback");
			throw new UnsupportedOperationException("Bad exception handing", e);
		}

	}

	
	
	
	public List<T> searchByCriteria(
			Map<? extends Enum<?>, Object> searchCriteria)
			throws RuntimeException {
		// TODO Auto-generated method stub
		return (List<T>) baseDao.search(searchCriteria, type);
	}

	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	protected abstract boolean isCreate(final T entity) throws RuntimeException;

	public List<T> getList(final T entity) throws RuntimeException {
		// TODO Auto-generated method stub
		return (List<T>) baseDao.listItems(entity);
	}

	public void delete(T entity) throws RuntimeException {
		// TODO Auto-generated method stub
		LOG.debug("Deleting the record.......................");
		try{
			baseDao.delete(entity);
			
		}catch(final Exception e){
			LOG.debug("Unable to delete the record...............");
			e.printStackTrace();
		}
		
	}

}
